<template>
  <div :id="'draw_area_'+ pid" class="draw-area" :class="{'read': draw === undefined}" oncontextmenu="return false" ondragstart="return false" onselectstart="return false" @click.stop="clickClear" :style="{'--theme': $store.getters.themeColor}">
    <!-- 模版 -->
    <canvas :id="'draw_canvas_'+ pid" :width="size.w" :height="size.h"></canvas>
    <!-- 按钮 -->
    <div v-if="draw && btns.length && !expand.includes(4)" class="draw-btns" :class="{'hide': drawing.includes(drawType)}">
			<i v-if="btns.includes(1)" class="btn iconfont icon-fuhao-huizhi" @click="doDrawing(0)" c-tip="标绘识别区域，单击开始标绘，双击完成标绘，右键取消" c-tip-placement="top"></i>
			<i v-if="btns.includes(8)" class="btn iconfont icon-youqiguanxian" @click="doDrawing(3)" c-tip="标绘油气管线，单击开始标绘，双击完成标绘，右键取消" c-tip-placement="top"></i>
			<i v-if="btns.includes(2)" class="btn iconfont icon-weizhi1" :class="{'on': isLocation}" @click="doDrawToMap({type: 1})" c-tip="设置定位点" c-tip-placement="top"></i>
			<i v-if="btns.includes(3)" class="btn iconfont icon-liulanqi" :class="{'on': isLayer}" @click="doDrawToMap({type: 2})" c-tip="图斑标绘识别区域" c-tip-placement="top"></i>
			<i v-if="btns.includes(4)" class="btn iconfont icon-pingbiquyu" @click="doDrawing(1)" c-tip="标绘屏蔽区域，单击开始标绘，双击完成标绘，右键取消" c-tip-placement="top"></i>
			<i v-if="btns.includes(5)" class="btn iconfont icon-zhixian" @click="doDrawing(2)" c-tip="标绘拌线，单击开始标绘，单击第二个点结束标绘，右键取消" c-tip-placement="top"></i>
			<i v-if="btns.includes(5)" class="btn iconfont icon-shuangjiantou" :class="bxArrow ? 'selected':''" @mouseenter="bxArrowTs = true" @mouseleave="bxArrowTs = false" @click.stop="bxArrowSelectShow" :c-tip="bxArrowTsShow ? '标绘拌线箭头，选择后给拌线标绘方向箭头':''" c-tip-placement="top">
				<span v-if="bxArrow" class="draw-arrow" @click.stop>
					<i class="iconfont icon-jiantou" @click="chooseBxArrow(1)"></i>
					<i class="iconfont icon-jiantou" @click="chooseBxArrow(2)"></i>
				</span>
			</i>
			<i v-if="btns.includes(6)" class="btn iconfont icon-baocun" @click="doSave()" c-tip="暂存" c-tip-placement="top"></i>
			<i v-if="btns.includes(7)" class="btn iconfont icon-cuowu-fullcopy" @click="clearDraw(false)" c-tip="清除标绘" c-tip-placement="top"></i>
    </div>
    <!-- 标绘编号 -->
    <template v-for="item in drawNumPosition">
      <div v-if="draw !== undefined" class="draw-num" :style="{'left': item.x + 'px', 'top': item.y + 'px'}" @click="doDrawChoose(item.bind, true);">{{ item.num }}</div>
    </template>
    <!-- 删除按钮 -->
    <div v-if="draw && selected && selected.remove && !selected.item.readonly" class="draw-remove" :style="{'left': selected.remove.x + 'px', 'top': selected.remove.y + 'px'}" @click="drawRemove()">
      <i class="iconfont icon-guanbi1"></i>
    </div>

    <div v-if="draw && selected && selected.drawColor && !selected.item.readonly" class="draw-color" :style="{'left': selected.drawColor.x + 'px', 'top': selected.drawColor.y + 'px'}">
      <el-color-picker popper-class="draw-area-color-picker" v-model="drawColor" size="small" @change="changeColor" @click.native="colorShow()"></el-color-picker>
    </div>

    <!-- 图斑信息 -->
    <div v-if="selected && selected.item && selected.item.layer && selected.layer" class="draw-layer" :class="{'on' : isBeyond}" :style="{'left': selected.layer.x + 'px', 'top': selected.layer.y + 'px'}" :title="selected.item.layer.tbbh" @click="doDrawChoose(selected.layer.bind, true);">{{ selected.item.layer.tbbh }}</div>
    <!-- 提示信息 -->
    <Ts ref="doDrawMessTs" />
  </div>
</template>
<script>
/* 引入全局js */
import {fabric} from 'fabric';
import {isPolygonsOverlap} from '@/utils/common';
import {getAlgorithmInfoBatch} from '@/api/video/video';
import Ts from './ts.vue';

export default {
  components: {
    Ts
  },
  props: {
    data: { //数据信息, deviceCode: 设备编码, channelCode: 通道编码, presetId: 预置位
      type: Object,
      default: () => ({})
    },
    draw: { //组件类型, undefined: 只查看, false: 查看可点击, true: 编辑
      default: undefined
    },
    btns: { //编辑按钮列表, 1: 识别区域, 2: 定位, 3: 图斑, 4: 屏蔽区域, 5: 拌线, 6: 暂存, 7: 清除 8:油气管线
      type: Array,
      default: () => ([])
    },
    expand: { //扩展功能,支持同时多种, 1: 关联算法, 2: 自动暂存, 3: 图斑管理新增, 4: 图斑管理修改、查看
      type: Array,
      default: () => ([])
    },
    algorithms: { //关联算法列表, expand包含关联算法时必传
      type: Array,
      default: () => ([])
    },
    isLayer: { //是否开启地图图斑功能
      default: false
    },
    isLocation: { //是否开启地图定位功能
      default: false
    },
    unDraw: { //不能标绘提示文字
      default: false
    },
    drawData: { //默认回填数据
      default: () => ([])
    }
  },
  data() {
    return {
      pid: this.getUUID(),//组件唯一id
      drawCanvas: false, //标绘模板
      drawObj: {}, //标绘对象 key为 设备编码_通道编码_标绘类型
      drawType: -1, //标绘类型, 0: 识别区域, 1: 屏蔽区域, 2: 拌线, 3: 油气管线
      drawing: [0, 1, 2, 3], //标绘中, 隐藏底部按钮
      bxArrow: false, //选择拌线箭头
      bxArrowTs: false, //选择拌线提示
      size: { //标绘模版大小
        w: 0,
        h: 0
      },
      selected: false, //选中标绘区域
      selectedLayer: false, //地图选中的图斑id
      drawNumPosition: [], //标绘编号定位
      isScreenFull: false, //是否全屏
      algorithmsRule: false, //算法校验规则
      drawBackDelay: [], //延迟回填标绘列表
      isBeyond: false,//标绘编号文本是否超出标绘范围
      pipelinePolyline: null,//管线的折线
      endArrow: null,//管线的终点箭头
      pipelineOption: {//管线的参数
        arrowWidth: 30,
        arrowHeight: 16,
      },
      drawColor: '#E9EC04',//管线标绘默认颜色
      drawColorOpc: 0.6,//管线标绘默认透明度
			polygonNoList: [],
    };
  },
  watch: {
    /**
     * 监听 默认回填数据
     */
    drawData: {
      handler: function(list) {
        this.doDrawBack(list);
      },
      immediate: true,
      deep: true
    },
    /**
     * 监听 关联算法列表
     */
    algorithms: {
      handler: function(list) {
        if(!this.expand.includes(1)) {
          return false;
        }
        list = JSON.parse(JSON.stringify(list));
        this.algorithmsRule = false;
        clearTimeout(this.getAlgorithmInfoBatchTiming);
        this.getAlgorithmInfoBatchTiming = setTimeout(() => {
          if(list && list.length) {
            getAlgorithmInfoBatch(list).then((resp) => {
              const unlike = this.algorithms.some((item, i) => item !== list[i]);
              if(unlike) {
                return false;
              }
              if(resp.code === 200) {
                this.algorithmsRule = resp.data || [];
              }else {
                this.algorithmsRule = [];
              }
            });
          }else {
            this.algorithmsRule = [];
          }
        }, 500);
      },
      immediate: true,
      deep: true
    }
  },
  computed: {
    /**
     * 选择拌线提示显示
     */
    bxArrowTsShow() {
      return !this.bxArrow && this.bxArrowTs;
    }
  },
  mounted() {
    this.resizeCanvas();
  },
  methods: {
    /**
     * 显示颜色画板
     */
    colorShow() {
      $('#draw_area_'+ this.pid +' .draw-area-color-picker').remove();
      this.$nextTick(() => {
        if(this.isScreenFull && $('.draw-area-color-picker').length) {
          $('#draw_area_'+ this.pid)[0].appendChild($('.draw-area-color-picker')[0]);
        }
      });
    },
    /**
     * 从地图接收数据
     */
    doMapToDraw({info} = {}) {
      console.log('%c 标绘--从地图接收数据==', 'color: blue', {info});
      if(info) {
        if(this.expand.includes(4)) {
          return false;
        }
        let {layer, selected, areaId, location} = info;
        const {layerId, freckleId, tbbh} = layer || {};
        const key = this.getKey(0);
        const has = this.drawObj[key]?.find(item => item.uuid === areaId || item.layer && item.layer.layerId === layerId && item.layer.freckleId === freckleId);
        if(location?.remove && has) {
          has.location = false;
        }
        if(layer?.clear) {
          this.drawObj[key].forEach(item => {
            if(item.layer) {
              this.drawRemove(item);
            }
          });
          this.selectedLayer = false;
        }
        if(location?.remove || layer?.clear) {
          return false;
        }
        if(selected) {
          this.selectedLayer = has?.layer || layer;
          if(!this.selected?.item?.uuid || this.selected?.item?.uuid !== has?.uuid) {
            this.doDrawSelect({
              target: {
                bind: has?.uuid
              }
            }, true);
          }
          if(layer && !has) {
            this.loadLayer(info);
          }
          if(location && has) {
            has.location = info.location;
          }
        }else {
          if(this.expand.includes(5)){
            this.clearDraw(true);
          }
          this.selectedLayer = false;
          this.doDrawSelect({}, true);
        }
      }
    },
    /**
     * 处理图斑信息
     */
    loadLayer(info) {
      const {layer, areaId, points,polygonNo} = info;
      if(areaId && points) {
        let readonly = this.expand.includes(3);
				//暂存数据回填可以修改
				if(info.fromTable){
					readonly = false;
				}
        this.doDrawBack([{
          type: 0,
          id: areaId,
          points,
          layer,
          location,
          polygonNo,
          readonly
        }], false, true, true);
      }else {
        if(this.expand.includes(3)) {
          this.loadExtand_3(layer);
        }
      }
    },
    /**
     * 处理扩展3标绘区域
     */
    loadExtand_3(layer) {
      const key = this.getKey(0);
      const list = this.drawObj[key] || [];
      for(let i = list.length - 1; i >= 0; i --) {
        // if(list[i].readonly) {
        //   continue;
        // }
        if(list[i].finish) {
          this.drawCanvas.remove(list[i].finish);
          list[i].circles.forEach((it) => {
            this.drawCanvas.remove(it);
          });
          list.splice(i, 1);
        }else {
          list[i].layer = layer;
        }
      }
      this.doDrawNumPosition();
      if(this.draw) {
        this.drawType = 0;
      }
    },
    /**
     * 从标绘传数据到地图
     */
    doDrawToMap({type, info, draws}) {
      let status;
      if(type === 1) {
        status = !this.isLocation;
      }
      if(type === 2) {
        status = !this.isLayer;
      }
      console.log('%c 标绘--发送数据到地图==', 'color: blue', {type, status, info, draws});
      try{
        this.$parent.doDrawToMap({type, status, info, draws});
      }catch (e){
        //console.log(e)
      }
      this.$emit('doDrawToMap', {type, status, info, draws});
    },
    /**
     * 高亮标绘
     */
    doDrawChoose(id, select, call = true) {
      if(select) {
        this.doDrawSelect({
          target: {
            bind: id
          }
        }, call);
        return false;
      }
      Object.keys(this.drawObj).forEach((key) => {
        this.drawObj[key].forEach((item) => {
          let on = false;
          if(item.uuid === id) {
            on = true;
          }
          const {fill} = this.getColor(item.type, on);
          item.finish.set({
            fill
          });
        });
      });
      this.drawCanvas.renderAll();
    },
    /**
     * 自适应画布
     */
    resizeCanvas() {
      this.initDraw();
      this.resizeObserver  = new ResizeObserver(() => {
        clearTimeout(this.timing);
        this.timing = setTimeout(() => {
          this.initDraw();
        }, 200);
      });
      this.resizeObserver.observe($('#draw_area_'+ this.pid)[0]);
    },
    /**
     * 初始化画布
     */
    initDraw() {
      const $drawArea = $('#draw_area_'+ this.pid);
      if(!$drawArea?.length) {
        return false;
      }
      const w = parseInt($drawArea.outerWidth());
      const h = parseInt($drawArea.outerHeight());
      this.resizeBtns();
      if(w !== this.size.w || h !== this.size.h) {
        console.log('%c 画布重置==', 'color: blue', w, h, this.size);
        this.drawType = -1;
        if(this.drawCanvas) {
          this.drawCanvas.dispose();
          this.drawCanvas = false;
        }
        this.size.w = w;
        this.size.h = h;
        this.$nextTick(() => {
          this.drawCanvas = new fabric.Canvas('draw_canvas_'+ this.pid, {
            fireRightClick: true, // 启用右键，button的数字为3
            stopContextMenu: true, // 禁止默认右键菜单
            hoverCursor: 'pointer', //鼠标样式
            moveCursor: 'default', //移动时鼠标样式
            selection: false //分组选择是否可用
          });
          this.drawCanvas.on({
            'mouse:down': (e) => { //鼠标按下
              if(this.drawing.includes(this.drawType)) {
                if(e.button === 3) {
                  if(this.drawType === 3){
                    this.doDrawPipelineCancel(e);
                  }else{
                    this.doDrawCancel(e);
                  }

                }else {
                  if(this.drawType === 3){
                    this.doDrawPipelineClick(e);
                  }else{
                    this.doDrawClick(e);
                  }
                }
                return false;
              }
              this.doDrawSelect(e, true);
            },
            'mouse:move': (e) => { //鼠标移动
              if(this.drawing.includes(this.drawType)) {
                if(this.drawType === 3){
                  this.doDrawPipelineMove(e);
                }else{
                  this.doDrawMove(e);
                }
              }
            },
            'mouse:dblclick': (e) => { //鼠标双击
              if(this.drawing.includes(this.drawType)) {
                if(this.drawType === 3){
                  this.doDrawPipelineFinish();
                }else{
                  this.doDrawFinish(undefined, undefined, undefined, undefined, undefined, e);
                }
              }
            },
            'object:moving': (e) => { //移动对象
              this.doDrawDrag(e);
            },
          });
          if(this.expand.includes(2) && this.draw) {
            this.drawType = 0;
          }
          Object.keys(this.drawObj).forEach((key) => {
            const list = this.drawObj[key];
            if(!list[list.length - 1]?.finish) {
              list.pop();
            }
            list.forEach((item, i) => {
              if(item.finish) {
                item.points = (item.pointsPer || []).map((it) => {
                  return {
                    x: it.x * w,
                    y: it.y * h
                  }
                });
                if(item.type === 3){
                  this.doDrawPipelineFinish(item.type, i, false, false);
                }else{
                  this.doDrawFinish(item.type, i, false, false);
                }
              }
            });
          });
          if(this.drawBackDelay.length) {
            this.drawBackDelay.forEach((item) => {
              this.doDrawBack(item.draw, item.append, item.select);
            });
            this.drawBackDelay = [];
          }
        });
      }
      this.checkScreenFull();
    },
    /**
     * 按钮自适应
     */
    resizeBtns() {
      this.$nextTick(() => {
        const $drawArea = $('#draw_area_'+ this.pid);
        if(!$drawArea?.length) {
          return false;
        }
        const w = parseInt($drawArea.outerWidth());
        const $btns = $drawArea.find('.draw-btns');
        if(!$btns?.length) {
          return false;
        }
        const btnW = 38 * 8 + 30;
        let scale = 1;
        if(btnW > w * 0.5) {
          scale = (w * 0.5) / btnW;
        }
        $btns[0].style.setProperty('--btnScale', scale);
        $btns.css({
          bottom: 16 * scale + 'px'
        });
      });
    },
    /**
     * 标绘点击
     */
    doDrawClick(e) {
      if(!this.checkBeforeDraw()) {
        return false;
      }
      if(!this.checkLayer()) {
        return false;
      }
      const key = this.getKey();
      const list = this.drawObj[key] = this.drawObj[key] || [];
      let layer = this.selectedLayer;
      if(!this.isLayer) {
        layer = false;
      }
      if(!list.length || list[list.length - 1]?.finish) {
        list.push({
          uuid: this.getUUID(), //唯一id
          type: this.drawType, //标会类型
          points: [], //标绘点位
          pointsPer: [], //标绘点位百分比
          lines: [], //标绘连接线
          circles: [], //选中时连接处大圆点
          finish: false, //完成的图形实例
          direction: false, //拌线箭头点位百分比
          directionFinish: false, //拌线箭头图形实例
          isUpdate: '3', //是否新增或修改, 1: 修改, 2: 未修改, 3: 新增
          layer //图斑
        });
      }
      const {stroke} = this.getColor();
      const {x, y} = e.pointer;
      const curr = list[list.length - 1];
      if(this.expand.includes(2) && !curr.points?.length) {
        this.doMessTs('单击开始标绘，双击结束，右键取消上一个标绘点');
      }
      const line = new fabric.Line([x, y, x, y], {
        selectable: false,
        strokeWidth: this.drawType !== 3 ? 3 : 12,
        strokeLineJoin: this.drawType !== 3 ? 'miter' : 'round',
        stroke
      });
      curr.points.push(e.pointer);
      curr.lines.push(line);
      this.drawCanvas.add(line);
      if(this.drawType === 2 && curr.lines.length === 2) {
        this.doDrawFinish(this.drawType);
      }
    },
    /**
     * 管线标绘点击
     */
    doDrawPipelineClick(e) {
      console.log('doDrawPipelineClick执行了', e)
      if(!this.checkBeforeDraw()) {
        return false;
      }
      const key = this.getKey();
      const list = this.drawObj[key] = this.drawObj[key] || [];
      const firstFlag = (!list.length || list[list.length - 1]?.finish);
      if(firstFlag){
        list.push({
          uuid: this.getUUID(), //唯一id
          type: this.drawType, //标会类型
          points: [], //标绘点位
          drawPoints: [], //显示的标绘点位
          pointsPer: [], //标绘点位百分比
          lines: [], //标绘连接线
          circles: [], //选中时连接处大圆点
          finish: false, //完成的图形实例
          direction: false, //拌线箭头点位百分比
          directionFinish: false, //拌线箭头图形实例
          isUpdate: '3', //是否新增或修改, 1: 修改, 2: 未修改, 3: 新增
        });
      }
      const {stroke,fill} = this.getColor();

      const curr = list[list.length - 1];

      const {x, y} = e.pointer;
      const {w, h} = this.size;
      curr.pointsPer.push({
        x: (x / w).toFixed(3),
        y: (y / h).toFixed(3)
      });
      curr.points.push(e.pointer);
      if (!firstFlag) {
        this.drawCanvas.remove(curr.pipelinePolyline);
      }
      curr.pipelinePolyline = new fabric.Polyline(curr.points, {
        selectable: false,
        bind: curr.uuid,
        strokeWidth: 12,
        strokeLineJoin: 'round',
        fill: fill,
        stroke,
      });
      this.drawCanvas.add(curr.pipelinePolyline);
    },
    /**
     * 标绘移动
     */
    doDrawMove(e) {
      const key = this.getKey();
      const list = this.drawObj[key];
      if(list?.length) {
        const curr = list[list.length - 1];
        if(curr.lines.length) {
          curr.lines[curr.lines.length - 1].set({
            x2: e.pointer.x,
            y2: e.pointer.y
          });
          this.drawCanvas.renderAll();
        }
      }
    },
    /**
     * 标绘移动
     */
    doDrawPipelineMove(e) {
      const key = this.getKey();
      const list = this.drawObj[key];
      if(list?.length) {
        const curr = list[list.length - 1];
        if(curr.pipelinePolyline) {
          this.drawCanvas.remove(curr.pipelinePolyline);//清理管线
          if(curr.moveEndArrow){//清理移动点箭头
            this.drawCanvas.remove(curr.moveEndArrow);
            curr.moveEndArrow = null;
          }

          const {stroke, fill} = this.getColor();

          let list = this.getPipelinePoints(curr.points, e.pointer);
          curr.pipelinePolyline = new fabric.Polyline(list, {
            selectable: false,
            bind: curr.uuid,
            strokeWidth: 12,
            strokeLineJoin: 'round',
            fill: fill,
            stroke,
            z: 2
          });
          this.drawCanvas.add(curr.pipelinePolyline);

          let points = JSON.parse(JSON.stringify(curr.points));
          points.push(e.pointer);
          let endArrow = this.drawEndArrow(points);
          curr.moveEndArrow = endArrow;
          this.drawCanvas.add(endArrow);
        }
      }
    },
    /**
     * 标绘回填
     */
    doDrawBack(draw = [], append, select = false, flag = false) {
      console.log('标绘回填',draw);
      if(!this.drawCanvas) {
        this.drawBackDelay.push({draw, append, select});
        return false;
      }
      if(!append) {
        this.clearDraw(flag);
      }
      const {w, h} = this.size;
      let choose;
      draw.forEach((item) => {
        item.type = item.type || 0;
        const key = this.getKey(item.type);
        this.drawObj[key] = this.drawObj[key] || [];
        const list = this.drawObj[key];
        const points = (item.pointsPer || item.points || []).map((it) => {
          return {
            x: it.x * w,
            y: it.y * h
          }
        });
        const uuid = item.uuid || item.areaId || item.id || this.getUUID(); //唯一id
        list.push({
          uuid, //唯一id
          type: item.type, //标会类型
          color: item.color,//管线颜色
          points, //标绘点位
          pointsPer: [], //标绘点位百分比
          lines: [], //标绘连接线
          circles: [], //选中时连接处大圆点
          finish: false, //完成的图形实例
          direction: item.direction, //拌线箭头点位百分比
          directionFinish: false, //拌线箭头图形实例
          isUpdate: item.id ? (item.isUpdate || '2') : '3', //是否新增或修改, 1: 修改, 2: 未修改, 3: 新增
          location: item.location, //定位
          polygonNo: item.polygonNo,
          maxPolygonNo: item.maxPolygonNo,
          layer: item.layer || false, //图斑
          readonly: item.readonly, //是否只读
          isAuto: item.isAuto || false
        });
        if(this.expand.includes(1) && (item.layer || item.location) && !choose) {
          choose = select = true;
        }
        if(item.type === 3){
          this.doDrawPipelineFinish(item.type, undefined, select);
        }else{
          this.doDrawFinish(item.type, undefined, select);
        }

        select = false;
      });
      this.doDrawToMap({
        draws: this.getAllDraw(0)
      })
    },
    /**
     * 标绘完成
     */
    doDrawFinish(type, index, select = true, call = true, update, e) {
      if(type !== undefined) {
        this.drawType = type;
      }
      const key = this.getKey();
      const list = this.drawObj[key] || [];
      if(index === undefined) {
        index = list.length - 1;
      }
      const curr = list[index];
      if(type === undefined) {
        if([0, 1].includes(this.drawType) && curr.points.length < 4) {
          this.doDrawCancel(e);
          return false;
        }
        curr.points.pop();
      }
      if(curr.finish) {
        this.drawCanvas.remove(curr.finish);
        this.drawCanvas.remove(curr.directionFinish);
      }
      if(!update) {
        curr.circles = [];
        curr.circles.forEach((item) => {
          this.drawCanvas.remove(item);
        });
      }
      curr.lines.forEach((item) => {
        this.drawCanvas.remove(item);
      });
      curr.lines = [];
      const {stroke, fill} = this.getColor();
      const {w, h} = this.size;
      const pn = [];
      curr.pointsPer = [];
      curr.points.forEach((item, i) => {
        curr.pointsPer.push({
          x: (item.x / w).toFixed(3),
          y: (item.y / h).toFixed(3)
        });
        const it = JSON.parse(JSON.stringify(item));
        if(it.x >= w - 3) {
          it.x = w - 3;
        }
        if(it.y >= h - 3) {
          it.y = h - 3;
        }
        pn.push(it);
        if(curr.readonly) {
          return false;
        }
        if(!update) {
          const circle = new fabric.Circle({
            hasControls: false,
            hasBorders: false,
            bind: curr.uuid,
            index: i,
            left: it.x - 6,
            top: it.y - 6,
            strokeWidth: 3,
            radius: 6,
            fill: '#fff',
            stroke,
            evented: true,
            visible: false
          });
          curr.circles.push(circle);
          this.drawCanvas.add(circle);
        }else {
          curr.circles[i].set({
            left: it.x - 6,
            top: it.y - 6,
          });
        }
      });
      const left = this.findLeftPaddingForRoof(pn);
      const top = this.findTopPaddingForRoof(pn);
      curr.finish = new fabric.Polygon(pn, {
        selectable: false,
        bind: curr.uuid,
        strokeWidth: 3,
        fill,
        stroke,
        left,
        top,
        z: 1,
      });
      this.drawCanvas.add(curr.finish);
      if(type === 2 && curr.direction) {
        if(curr.direction[0].x < curr.direction[1].x) {
          this.chooseBxArrow(1, curr);
        }else {
          this.chooseBxArrow(2, curr);
        }
      }
      if(update && curr.isUpdate === '2') {
        curr.isUpdate = '1';
      }
      this.doDrawNumPosition();
      if(select || this.selected?.item?.uuid === curr.uuid) {
        this.doDrawChoose(curr.uuid, true, call);
      }
      let t = -1;
      if(this.draw && this.expand.includes(1)) {
        t = 300;
      }
      this.checkRepeat(false, t);
      if(this.draw && this.expand.includes(4)) {
        this.doSave();
      }
      this.drawType = -1;
    },
    /**
     * 管线标绘完成
     */
    doDrawPipelineFinish(type, index, select = true, call = true) {
      if(type != null) {
        this.drawType = type;
      }
      const key = this.getKey();
      const list = this.drawObj[key] || [];
      if(index == null) {
        index = list.length - 1;
      }
      const curr = list[index];
      if(type == null) {
        curr.points.pop();
      }
      if(curr.finish) {
        this.drawCanvas.remove(curr.finish);
      }
      if(type != null && curr.color){
        this.drawColor = curr.color;
      }
      let {stroke, fill} = this.getColor();

      const {w, h} = this.size;
      const pn = [];
      curr.pointsPer = [];
      curr.points.forEach((item, i) => {
        curr.pointsPer.push({
          x: (item.x / w).toFixed(3),
          y: (item.y / h).toFixed(3)
        });
        const it = JSON.parse(JSON.stringify(item));
        if(i < curr.points.length - 1){//最后一个点要留出箭头,单独处理
          pn.push(it);
        }

        if(curr.readonly) {
          return false;
        }
      });

      if(curr.moveEndArrow){//清理移动点箭头
        this.drawCanvas.remove(curr.moveEndArrow);
        curr.moveEndArrow = null;
      }
      let endArrow = this.drawEndArrow(curr.points);
      curr.moveEndArrow = endArrow;
      this.drawCanvas.add(endArrow);

      curr.color = stroke;
      const showPoints = this.getPipelinePoints(pn, curr.points[curr.points.length - 1]);

      this.drawCanvas.remove(curr.pipelinePolyline);
      curr.pipelinePolyline = null;
      curr.finish = new fabric.Polyline(showPoints, {
        selectable: false,
        bind: curr.uuid,
        strokeWidth: 12,
        strokeLineJoin: 'round',
        fill: fill,
        stroke,
      });
      this.drawCanvas.add(curr.finish);

      if(select || this.selected?.item?.uuid === curr.uuid) {
        this.doDrawChoose(curr.uuid, true, call);
      }

      if(this.draw && this.expand.includes(2)) {
        this.doSave();
      }
      this.drawType = -1;
    },
    /**
     * 根据绘制的路径判断终点箭头的旋转方向
     * @param coords 点集合
     * @returns {number}
     */
    getTriangleAngleByCoords(coords, flag) {
      if (coords.length < 2){
        return 0;
      }
      // 最后一个点
      const x2 = coords[coords.length - 1].x;
      const y2 = coords[coords.length - 1].y;
      // 倒数第二个点
      const x1 = coords[coords.length - 2].x;
      const y1 = coords[coords.length - 2].y;
      let angle = 0, x, y;
      x = (x2 - x1);
      y = (y2 - y1);

      if (x === 0) {
        angle = (y === 0) ? 0 : (y > 0) ? Math.PI / 2 : Math.PI * 3 / 2;
      } else if (y === 0) {
        angle = (x > 0) ? 0 : Math.PI;
      } else {
        angle = (x < 0) ? Math.atan(y / x) + Math.PI : (y < 0) ? Math.atan(y / x) + (2 * Math.PI) : Math.atan(y / x);
      }

      if(flag){
        return angle;
      }else{
        return (angle * 180 / Math.PI + 90);
      }
    },
    /**
     * 获取管线绘制终点的坐标
     * @param coords
     * @returns {{x: number, y: number}|boolean}
     */
    getDrawEndPoint(coords){
      if (coords.length < 2){
        return false;
      }
      let coordinate = coords[coords.length-1];
      // 弧度
      let radian = this.getTriangleAngleByCoords(coords, true);
      const y = Math.sin(radian) * this.pipelineOption.arrowHeight;
      const x = Math.cos(radian) * this.pipelineOption.arrowHeight;
      let xEnd = coordinate.x - x;
      let yEnd = coordinate.y - y;
      return { x: xEnd, y: yEnd };
    },
    /**
     * 获取管线绘制图像的点数组
     * @param points 绘制点的数组
     * @param coordinate 最后点坐标
     */
    getPipelinePoints(points, coordinate){
      let points2 = JSON.parse(JSON.stringify(points));
      points2.push(coordinate);
      const endPoint = this.getDrawEndPoint(points2);
      let list = JSON.parse(JSON.stringify(points));
      list.push(endPoint);
      return list;
    },
    /**
     * 绘制终点箭头
     * @param coords
     * @returns {*}
     */
    drawEndArrow(coords) {
      let left = coords[coords.length - 1].x;
      let top =  coords[coords.length - 1].y;
      const angle = this.getTriangleAngleByCoords(coords);
      const stroke = this.hexToRgb(this.drawColor, this.drawColorOpc);
      return new fabric.Triangle({
        width: this.pipelineOption.arrowWidth,
        height: this.pipelineOption.arrowHeight,
        left: left,
        top: top,
        fill: stroke,
        // fill: 'transparent',
        borderColor: 'rgba(0, 0, 0, 0)',
        transparentCorners: true,
        cornerStrokeColor: stroke,
        strokeWidth: 0,
        stroke: stroke,
        angle,
        opacity: 1,
        centeredRotation: true,
        originX: 'center',
        originY: 'top',
        selectable: false,// 禁止选中
        hasControls: false, // 当设置为 `false` 时，对象的控件不显示并且不能用于操作对象
        hasBorders: false,
      });
    },
    /**
     * 清理终点箭头
     */
    cleanEndArrow(){
      const list = this.drawObj[key];
      if(list?.length) {
        const curr = list[list.length - 1];
        for (const endArrow of curr.endArrow) {
          this.drawCanvas.remove(endArrow);
        }
        curr.endArrow = [];
      }
    },
    /**
     * 标绘编号定位
     */
    doDrawNumPosition(remove) {
      const po = [];
      const drawNum = [0, 0, 0];
      let maxPolygonNo = this.data.maxPolygonNo;
      let newPolygonNo = ++maxPolygonNo;
			if(this.expand.includes(3)) {
				let key = this.data.deviceCode + '_' + this.data.channelCode + '_' + this.data.presetId;
				if(this.polygonNoList[key]){//暂存列表中有该预置位的电子围栏
					newPolygonNo += this.polygonNoList[key];
				}
			}
      Object.keys(this.drawObj).forEach((key) => {
        const list = this.drawObj[key];
        console.log('%c 标绘编号定位------list: ','color: #FAC800',list);
        list.forEach((item) => {
          if(item.type === 3){
            return false;
          }
          item.drawNum = ++ drawNum[item.type];
          const p = this.showSelectedOpt(item, true);
          po.push({
            num: item.polygonNo?item.polygonNo:maxPolygonNo?newPolygonNo:item.drawNum,
            ...p
          });
          if(remove && item.location) {
            this.doDrawToMap({info: item});
          }
        });
      });
      this.drawNumPosition = po;
    },
    /**
     * 拌线箭头显示隐藏
     */
    bxArrowSelectShow() {
      const b = !this.bxArrow;
      const key = this.getKey(2);
      const list = this.drawObj[key] || [];
      if(b && !list.length) {
        this.doMessTs('请先标绘拌线后再标绘方向箭头');
        return false;
      }
      if(b && this.selected?.item?.type !== 2) {
        this.doMessTs('请先选中拌线后再标绘方向箭头');
        return false;
      }
      this.bxArrow = b;
    },
    /**
     * 拌线箭头选择
     */
    chooseBxArrow(type, curr = this.selected?.item) {
      this.bxArrow = false;
      this.bxArrowTs = false;
      const {w, h} = this.size;

      let x0, y0, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6;

      if(curr.points[0].x < curr.points[1].x) {
        x1 = curr.points[0].x;
        y1 = curr.points[0].y;
        x2 = curr.points[1].x;
        y2 = curr.points[1].y;
      }else {
        x1 = curr.points[1].x;
        y1 = curr.points[1].y;
        x2 = curr.points[0].x;
        y2 = curr.points[0].y;
      }

      x0 = (x1 + x2) / 2;
      y0 = (y1 + y2) / 2;
      if(x1 === x2) {
        x3 = x1 - 0.05 * w;
        y3 = y0;
        x4 = x1 + 0.05 * w;
        y4 = y0;
      }else if(y1 === y2) {
        x3 = x0;
        y3 = y0 - 0.05 * w;
        x4 = x0;
        y4 = y0 + 0.05 * w;
      }else{
        const a = Math.atan(Math.abs(x0 - x1) / Math.abs(y0 - y1));
        x3 = x0 - 0.05 * w * Math.cos(a);
        y3 = y0 - 0.05 * w * Math.sin(a);
        x4 = x0 + 0.05 * w * Math.cos(a);
        y4 = y0 + 0.05 * w * Math.sin(a);
        if(y1 < y2) {
          y3 = y0 + 0.05 * w * Math.sin(a);
          y4 = y0 - 0.05 * w * Math.sin(a);
        }
      }

      x3 = x3 < 0 ? 0 : x3;
      x3 = x3 > w ? w : x3;
      y3 = y3 < 0 ? 0 : y3;
      y3 = y3 > h ? h : y3;
      x4 = x4 < 0 ? 0 : x4;
      x4 = x4 > w ? w : x4;
      y4 = y4 < 0 ? 0 : y4;
      y4 = y4 > h ? h : y4;

      if(type === 1) {
        x5 = x3;
        y5 = y3;
        x6 = x4;
        y6 = y4;
      }else {
        x5 = x4;
        y5 = y4;
        x6 = x3;
        y6 = y3;
      }
      curr.direction = [{
        x: (x5 / w).toFixed(3),
        y: (y5 / h).toFixed(3)
      }, {
        x: (x6 / w).toFixed(3),
        y: (y6 / h).toFixed(3)
      }];
      this.countArrow(x0, y0, x5, y5, x6, y6, curr);
    },
    /**
     * 计算箭头
     */
    countArrow(x0, y0, x1, y1, x2, y2, curr) {
      let dx = x2 - x1, dy = y2 - y1;
      let angle = Math.atan2(dy, dx);
      angle *= 180 / Math.PI;
      const w = this.size.w * 0.1;
      const points = [];
      points.push({
        x: x0 - w / 2 - 12,
        y: y0 - 2
      });
      points.push({
        x: x0 + w / 2,
        y: y0 - 2
      });
      points.push({
        x: x0 + w / 2,
        y: y0 - 7
      });
      points.push({
        x: x0 + w / 2 + 15,
        y: y0
      });
      points.push({
        x: x0 + w / 2,
        y: y0 + 7
      });
      points.push({
        x: x0 + w / 2,
        y: y0 + 2
      });
      points.push({
        x: x0 - w / 2 - 12,
        y: y0 + 2
      });
      if(curr.directionFinish) {
        this.drawCanvas.remove(curr.directionFinish);
      }
      const left = this.findLeftPaddingForRoof(points);
      const top = this.findTopPaddingForRoof(points);
      const {fill} = this.getColor(2);
      const arrow = new fabric.Polygon(points, {
        selectable: false,
        bind: curr.uuid,
        strokeWidth: 1,
        fill,
        stroke: '#fff',
        left,
        top,
      });
      curr.directionFinish = arrow;
      this.drawCanvas.add(arrow);
      curr.directionFinish.rotate(angle);
    },
    /**
     * 取消标绘
     */
    doDrawCancel(e) {
      const key = this.getKey();
      const list = this.drawObj[key];
      if(list?.length) {
        const curr = list[list.length - 1];
        if(!curr.finish && curr.lines.length) {
          this.drawCanvas.remove(curr.lines[curr.lines.length - 1]);
          curr.lines.pop();
          curr.points.pop();
          if(curr.lines.length) {
            curr.lines[curr.lines.length - 1].set({
              x2: e.pointer.x,
              y2: e.pointer.y
            });
          }else {
            list.pop();
          }
          this.drawCanvas.renderAll();
        }
      }
      if(!list?.length || list[list.length - 1].finish || !list[list.length - 1].lines.length) {
        this.drawType = -1;
        if(this.draw && this.expand.includes(2)) {
          this.drawType = 0;
        }
      }
    },
    /**
     * 取消标绘
     */
    doDrawPipelineCancel(e) {
      const key = this.getKey();
      const list = this.drawObj[key];
      if(list?.length) {
        const curr = list[list.length - 1];
        if(!curr.finish && curr.points.length) {
          curr.points.pop();
          this.doDrawPipelineMove(e);
        }
      }
      if(!list?.length || list[list.length - 1].finish || !list[list.length - 1].points.length) {
        this.drawType = -1;
        const curr = list[list.length - 1];
        if(curr.moveEndArrow){//清理移动点箭头
          this.drawCanvas.remove(curr.moveEndArrow);
          curr.moveEndArrow = null;
        }
      }
    },
    /**
     * 选中标绘
     */
    doDrawSelect(e = {}, call) {
      this.selected = false;
      const bind = e?.target?.bind;
      Object.keys(this.drawObj).forEach((key) => {
        this.drawObj[key].forEach((item) => {
          if (item.type !== 3) {
            let visible = false, on = false;
            if (item.uuid === bind) {
              visible = true;
              on = true;
              item.selected = true;
              if (item.type !== 0) {
                item.selected = false;
              }
              if (call) {
                setTimeout(() => {
                  this.selectedLayer = item.layer || false;
                  this.doDrawToMap({info: item});
                });
              }
              this.drawCanvas.bringToFront(item.finish);
            } else {
              if (item.selected) {
                item.selected = false;
                if (call && !this.expand.includes(4)) {
                  if(item.layer?.layerId === this.selectedLayer?.layerId && item.layer?.freckleId === this.selectedLayer?.freckleId) {
                    this.selectedLayer = false;
                  }
                  this.doDrawToMap({info: item});
                }
              }
            }
            if (item.finish) {
              const {fill} = this.getColor(item.type, on);
              item.finish.set({
                fill
              });
            }
            if (this.draw) {
              item.circles.forEach((it) => {
                it.set({
                  visible
                });
                this.drawCanvas.bringToFront(it);
              });
            }
          }

          if(item.uuid === bind) {
            if (item.type === 3) {
              this.showSelectedOpt(item, undefined, true);
            }else{
              this.showSelectedOpt(item);
            }
          }
        });
      });
      Object.keys(this.drawObj).forEach((key) => {
        this.drawObj[key].forEach((item) => {
          if (item.type === 3) {//管线置顶, 防止被识别区域盖住
            this.drawCanvas.bringToFront(item.finish);
          }
        });
      });

      this.drawCanvas.renderAll();
    },
    /**
     * 显示选中标绘操作
     * lastFlag 显示在最后一个点的位置
     */
    showSelectedOpt(item, drawNum, lastFlag) {
      const {w, h} = this.size;
      const first = lastFlag == null ? item.points[0] : item.points[item.points.length - 1];
      const remove = {
        bind: item.uuid,
        x: lastFlag != null ? first.x : first.x - 26,
        y: lastFlag != null ? first.y : first.y - 8
      };
      if(remove.x < 0) {
        remove.x = first.x + 10;
      }
      if(remove.y < 0) {
        remove.y = 0;
      }
      if(remove.y > h - 16) {
        remove.y = h - 16;
      }
      if(remove.x > w - 16){
        remove.x = w - 16;
      }
      const num = {
        bind: item.uuid,
        x: remove.x,
        y: remove.y + 20
      };
      if(lastFlag != null){
        if(num.x > w - 32) {
          num.x = remove.x - 16;
        }
        if(num.y > h - 32) {
          num.y = remove.y - 32;
        }
      }else{
        if(num.x > w - 28) {
          num.x = remove.x - 12;
        }
        if(num.y > h - 28) {
          num.y = remove.y - 30;
        }
      }

      if(drawNum) {
        return num;
      }
      let layer;
      if(item.type === 0) {
        const center = item.finish.getCenterPoint();
        layer = {
          bind: item.uuid,
          x: center.x - 2,
          y: center.y - 45
        }
      }
      this.selected = {
        remove,
        layer,
        item
      }
      if(item.type === 3){
        this.selected.drawColor = num;
      }else{
        this.computeTextSize(this.selected.layer);
      }
    },
    /**
     * 标绘拖拽
     */
    doDrawDrag(e) {
      const bind = e?.target?.bind;
      if(bind) {
        Object.keys(this.drawObj).forEach((key) => {
          this.drawObj[key].forEach((item, i) => {
            const {uuid, type, points} = item;
            if(uuid === bind) {
              const index = e.target.index;
              const {w, h} = this.size;
              let {x, y} = e.pointer;
              if(x < 0) {
                x = 0;
              }
              if(x > w) {
                x = w
              }
              if(y < 0) {
                y = 0;
              }
              if(y > h) {
                y = h;
              }
              points[index] = {
                x,
                y
              };
              delete item.isAuto;
              delete item.isSaved;
              this.doDrawFinish(type, i, true, false, true);
            }
          });
        });
      }
    },
    /**
     * 删除标绘
     */
    drawRemove(item = this.selected.item) {
      const key = this.getKey(item.type);
      this.drawObj[key].forEach((ite, i) => {
        if(ite.uuid === item.uuid) {
          this.drawObj[key].splice(i, 1);
        }
      });
      this.drawCanvas.remove(item.finish);
      this.drawCanvas.remove(item.directionFinish);
      if(item.moveEndArrow){
        this.drawCanvas.remove(item.moveEndArrow);
      }
      item.circles.forEach((it) => {
        this.drawCanvas.remove(it);
      });
      if(this.selected?.item?.uuid === item.uuid) {
        this.selected = false;
      }
      if(this.draw && this.expand.includes(2)) {
        this.drawType = 0;
        // this.doSave();
      }
      item.remove = true;
      this.doDrawToMap({info: item});
      this.doDrawNumPosition(true);
    },
    /**
     * 查询所有已标绘
     */
    getAllDraw(type) {
      const list = [];
      const all = [];
      Object.keys(this.drawObj).forEach((key) => {
        this.drawObj[key].forEach((item) => {
          if(item.finish) {
            all.push(item);
            if(type !== undefined && type === item.type) {
              list.push(item);
            }
          }
        });
      });
      if(type !== undefined) {
        return list;
      }
      return all;
    },
    /**
     * 暂存标绘
     */
    doSave(fn) {
      if(!this.checkBeforeDraw()) {
        return false;
      }
      if(!this.checkAlgorithms([0, 1, 2], true)) {
        return false;
      }
      //算法配置历史数据处理, 查看显示多个没问题，想要再编辑保存，就得把其他的删了，留下一个。
      if(this.expand.includes(1)){//算法配置
        let count = 0; //已标绘数量
        Object.keys(this.drawObj).forEach((key) => {
          this.drawObj[key].forEach((item) => {
            if(item.layer?.freckleId) {
              count ++;
            }
          });
        });
        if(count > 1){
          this.doMessTs('一个算法任务只能选择一个图斑且只能标绘一个电子围栏');
          return false;
        }
      }

      let t = -1;
      if(this.expand.includes(1)) {
        t = 0;
      }
      this.checkRepeat(() => {
        let count = 0; //已标绘数量
        let b = false; //拌线是否标绘方向箭头
        Object.keys(this.drawObj).forEach((key) => {
          this.drawObj[key].forEach((item) => {
            if(item.finish && item.type !== 3) {
              count ++;
              if(item.type === 2 && !item.direction) {
                b = true;
              }
            }
          });
        });
        if(b) {
          this.doMessTs('请标绘箭头后再保存算法任务');
          return false;
        }
        if(!this.expand.includes(2)) {
          if(count === 0) {
            const type = 0;
            if(!this.checkLayer(type, count)) {
              return false;
            }
            let layer = this.selectedLayer;
            if(!this.isLayer) {
              layer = false;
            }
            const draw = [{
              type: type,
              points: [{
                x: 0.001,
                y: 0.001
              },{
                x: 0.999,
                y: 0.001
              },{
                x: 0.999,
                y: 0.999
              },{
                x: 0.001,
                y: 0.999
              }],
              isAuto: true,
              layer
            }];
            this.doDrawBack(draw, true);
          }
        }
        const list = [];
        Object.keys(this.drawObj).forEach((key) => {
          this.drawObj[key].forEach((item) => {
            if (item.type === 3) {//管线置顶, 防止被识别区域盖住
              this.drawCanvas.bringToFront(item.finish);
            }
            item.isSaved = true;
            if(item.finish && !item.readonly) {
              list.push(item);
            }
          });
        });
        console.log('%c 标绘暂存==', 'color: blue', list);
        if(fn) {
          fn(list);
          return false;
        }
				if(this.expand.includes(3)) {
					this.getPolygonNo();
				}
        this.$emit('doSave', list);
      }, t);
    },
		/**
		 * 处理电子围栏编号
		 */
		getPolygonNo(){
			let key = this.data.deviceCode + '_' + this.data.channelCode + '_' + this.data.presetId;
			if(this.polygonNoList[key]){//暂存列表中有该预置位的电子围栏
				this.polygonNoList[key] += 1;
			}else{
				this.polygonNoList[key] = 1;
			}
		},
    /**
     * 清除标绘
     */
    clearDraw(flag) {
      this.drawType = -1;
      if(this.drawCanvas) {
        this.drawCanvas.clear();
      }
      const item = this.selected?.item || {};
      this.selected = false;
      this.drawObj = {};
      if(this.draw && this.expand.includes(2)) {
        this.drawType = 0;
      }
      this.selectedLayer = false;
      const info = {
        clear: true
      };
      if(!flag){
        this.doDrawToMap({info});
      }
      this.doDrawNumPosition();
    },
    /**
     * 标绘操作 type 0: 标绘识别区域, 1: 标绘屏蔽区域, 2: 标绘拌线 ,3: 管线
     */
    doDrawing(type) {
      if(!this.checkBeforeDraw()) {
        return false;
      }
      if (type === 3) {//管线
        if (!this.checkPipeline()){
          return false;
        }
      } else {//非管线
        if (!this.checkAlgorithms([type])) {
          return false;
        }
      }

      if(!this.checkLayer(type)) {
        return false;
      }


      const a = []; //已标绘的 识别区域+屏蔽区域
      const b = []; //已标绘的 拌线
      Object.keys(this.drawObj).forEach((key) => {
        this.drawObj[key].forEach((item) => {
          if(item.type === 2) {
            b.push(item);
          }else {
            if(item.type !== 3){
              a.push(item);
            }
          }
        });
      });
      if([0, 1].includes(type) && b.length) {
        this.doMessTs('算法识别区域、算法屏蔽区域不能与拌线同时设置，请清除拌线后再试。');
        return false;
      }
      if(type === 2 && a.length) {
        this.doMessTs('拌线不能与算法识别区域、算法屏蔽区域同时设置，请清除算法识别区域、算法屏蔽区域后再试。');
        return false;
      }
      if(this.selected) {
        this.doDrawSelect({}, true);
      }
      this.drawType = type;
      if(this.drawing.includes(type)) {
        this.doMessTs('单击开始标绘，双击结束，右键取消上一个标绘点');
      }
    },
    /**
     * 精准计算top
     */
    findTopPaddingForRoof(roofPoints) {
      let result = 999999;
      roofPoints.forEach((i) => {
        if (i.y < result) {
          result = i.y;
        }
      });
      return Math.abs(result);
    },
    /**
     * 精准计算left
     */
    findLeftPaddingForRoof(roofPoints) {
      let result = 999999;
      roofPoints.forEach((i) => {
        if (i.x < result) {
          result = i.x;
        }
      });
      return Math.abs(result);
    },
    /**
     * 生成标绘颜色
     */
    getColor(type = this.drawType, on) {
      let stroke, fill;
      if(type === 0) {
        stroke = 'rgba(85, 195, 246, 1)';
        fill = 'rgba(19, 35, 49, 0.3)';
      }
      if(type === 1) {
        stroke = 'rgba(202, 57, 49, 1)';
        fill = 'rgba(80, 18, 16, 0.3)';
      }
      if(type === 2) {
        stroke = 'rgba(238, 34, 30, 1)';
        fill = stroke;
      }
      if(type === 3) {
        stroke = this.hexToRgb(this.drawColor, this.drawColorOpc);
        fill = 'rgba(0, 0, 0, 0)';
      }
      if(on) {
        fill = 'rgba(241,161,57,0.3)';
      }
      return {stroke, fill};
    },
    /**
     * 生成key
     */
    getKey(type = this.drawType) {
      return type;
    },
    /**
     * 生成uuid
     */
    getUUID() {
      const crypto = window.crypto || window.msCrypto;
      const array = new Uint32Array(1);
      const r = crypto.getRandomValues(array)[0] ;
      return Date.now() + '999' + r;
    },
    /**
     * 点击清除
     */
    clickClear() {
      this.bxArrow = false;
    },
    /**
     * 校验是否存在重复区域
     */
    checkRepeat(fn, t = 0){
      if(t < 0) {
        fn && fn();
        return false;
      }
      clearTimeout(this.validateRepeatTiming);
      this.validateRepeatTiming = setTimeout(() => {
        let repeat = false;
        let repeatName = '';
        Object.keys(this.drawObj).forEach((key) => {
          const list = this.drawObj[key];
          for (let i = 0; i < list.length; i++) {
            if(i === 0) {
              continue;
            }
            for (let j = i - 1; j >= 0; j--) {
              if(!isPolygonsOverlap(list[i].pointsPer,list[j].pointsPer)){
                continue;
              }
              repeat = true;
              const sp = key.split('_');
              const type = sp[sp.length - 1];
              if(type === '0'){
                repeatName = '识别区域';
              }else if(type === '1'){
                repeatName = '屏蔽区域';
              }else{
                repeatName = '拌线';
              }
              break;
            }
            if(repeat){
              break;
            }
          }
        });
        if(repeat){
          this.doMessTs(repeatName + '不可重叠');
        }else{
          fn && fn();
        }
      }, t);
    },
    /**
     * 标绘前校验
     */
    checkBeforeDraw() {
      if(this.expand.includes(1) && this.data.posType === '') {
        this.doMessTs('请选择算法归属');
        return false;
      }
      if(this.expand.includes(1) && this.data.posType === 2 && !this.data.presetId) {
        this.doMessTs('请选择预置位');
        return false;
      }
      if(this.expand.includes(2) && !this.data.presetId) {
        this.doMessTs('请选择预置位');
        return false;
      }
      if(this.unDraw) {
        this.doMessTs(this.unDraw);
        return false;
      }
      return true;
    },
    /**
     * 校验图斑
     */
    checkLayer(drawType = this.drawType, count) {
      console.log(this.selectedLayer);
      if(!this.isLayer) {
        return true;
      }
      if(count === 0) {
        this.doMessTs('请标绘电子围栏后暂存。');
        return false;
      }
      if(drawType !== 0 && (!this.selectedLayer || this.selected?.item?.layer?.layerId === this.selectedLayer.layerId && this.selected?.item?.layer?.freckleId === this.selectedLayer.freckleId)) {
        return true;
      }
      if(this.selectedLayer && drawType !== 0) {
        this.doMessTs('图斑只支持识别区域。');
        return false;
      }
      if(!this.selectedLayer) {
        let ts = '请在地图中选择图斑后标绘。';
        if(this.expand.includes(1)) {
          ts = '请在地图中选中图斑后再进行标绘，如需单独标绘请退出图斑标绘识别区域功能。';

          //算法配置若已标绘绑定图斑的电子围栏,再次标绘给出提示
          if(this.verifyFreckleBind()){
            this.doMessTs('一个算法任务只能选择一个图斑且只能标绘一个电子围栏');
            return false;
          }
        }
        this.doMessTs(ts);
        return false;
      }
      if(this.selectedLayer?.disable || (this.selected?.item?.layer?.layerId === this.selectedLayer.layerId && this.selected?.item?.layer?.freckleId === this.selectedLayer.freckleId)) {
        if(this.expand.includes(1)) {//算法配置若已标绘绑定图斑的电子围栏,再次标绘给出提示
          if(this.verifyFreckleBind()){
            this.doMessTs('一个算法任务只能选择一个图斑且只能标绘一个电子围栏');
            return false;
          }
        }
        this.doMessTs('图斑已标绘电子围栏，请选择其他图斑。');
        return false;
      }
      return true;
    },
    verifyFreckleBind(){
      //算法配置若已标绘绑定图斑的电子围栏,再次标绘给出提示
      let count = 0; //已标绘数量
      Object.keys(this.drawObj).forEach((key) => {
        this.drawObj[key].forEach((item) => {
          if(item.layer?.freckleId) {
            count ++;
          }
        });
      });
      return count > 0;
    },
    /**
     * 校验算法
     */
    checkAlgorithms(types = [], flag) {
      if(!this.expand.includes(1)) { //关联算法
        return true;
      }
      if(!this.algorithms?.length) {
        this.doMessTs('请选择算法');
        return false;
      }
      if(!this.algorithmsRule) {
        this.doMessTs('正在获取算法配置信息');
        return false;
      }
      let b = true;
      for(const type of types) {
        let typeName, value, algorithmNames = '', desc = '';
        const key = this.getKey(type);
        this.algorithmsRule.forEach((item) => {
          let x = true;
          if(type === 0) {
            typeName = '识别区域';
            value = item.supportAlarmAreaList;
            x = this.drawObj[key] && this.drawObj[key][0]?.finish;
            if(flag) {
              x = this.drawObj[key] && this.drawObj[key][1]?.finish;
            }
            desc = '多个';
          }else if(type === 1) {
            typeName = '屏蔽区域';
            value = item.supportShield;
            if(flag) {
              x = this.drawObj[key] && this.drawObj[key][0]?.finish;
            }
          }else if(type === 2) {
            typeName = '拌线/箭头';
            value = item.supportTripThread;
            if(flag) {
              x = this.drawObj[key] && this.drawObj[key][0]?.finish;
            }
          }
          if(String(value) !== '1' && x) {
            if(algorithmNames) {
              algorithmNames += '、';
            }
            algorithmNames += item.algorithmName;
            b = false;
          }
        });
        if(!b) {
          if(this.algorithmsRule.length === 1) {
            this.doMessTs('该算法不支持标绘' + desc + typeName);
          }else {
            this.doMessTs(algorithmNames + ' 算法不支持标绘' + desc + typeName + '，如仍需标绘请重新选择算法');
          }
          break;
        }
      }
      return b;
    },
    /**
     * 校验管线
     */
    checkPipeline(){
      const key = this.getKey(3);
      const list = this.drawObj[key] || [];
      if(list.length > 0 && list[0].points.length){
        this.doMessTs('请删除已标绘的管线后重新标绘');
        return false;
      }else{
        return true;
      }
    },
    /**
     * 校验是否全屏
     */
    checkScreenFull() {
      const a = document.mozFullScreen || document.fullScreen || document.webkitIsFullScreen;
      const b = document.webkitRequestFullScreen || document.mozRequestFullScreen || document.msFullscreenEnabled;
      this.isScreenFull = a || b;
    },
    /**
     * 提示
     */
    doMessTs(mess) {
      this.$refs.doDrawMessTs.doMessTs(mess, true);
    },
    /**
     * 计算图斑text是否超出外层Div
     */
    computeTextSize(item) {
      this.$nextTick(()=> {
        let x = item.x;
        let boxW = $('.draw-area').width();
        let textW = $('.draw-layer').width();
        if(boxW < textW + x + 10) { //10 是流出10像素的容错
          this.isBeyond = true;
          this.selected.layer.x = this.selected.layer.x - textW - 10; //10 是流出10像素的容错
        }else {
          this.isBeyond = false;
        }
      })
    },
    /**
     * hex 转 rgba
     * @param hexValue
     * @param opc
     * @returns {*|string}
     */
    hexToRgb(hexValue, opc) {
      let rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
      let hex = hexValue.replace(rgx, function(m, r, g, b) {
        return r + r + g + g + b + b;
      });
      let rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
      if(!rgb){
        return hexValue;
      }
      let r1 = parseInt(rgb[1], 16);
      let g1 = parseInt(rgb[2], 16);
      let b1 = parseInt(rgb[3], 16);
      return 'rgba(' + r1 + ',' + g1 + ',' + b1 + ',' + opc + ')';
    },
    /**
     * 更改管线颜色
     */
    changeColor(){
      const list = this.drawObj[this.selected.item.type] || [];
      const index = list.length - 1;
      const curr = list[index];
      const {fill} = this.getColor();
      const stroke = this.hexToRgb(this.drawColor, this.drawColorOpc);
      curr.color = stroke;
      const pn = [];

      curr.points.forEach((item, i) => {
        const it = JSON.parse(JSON.stringify(item));
        if(i < curr.points.length - 1){//最后一个点要留出箭头,单独处理
          pn.push(it);
        }
      });
      const showPoints = this.getPipelinePoints(pn, curr.points[curr.points.length - 1]);

      //画线
      this.drawCanvas.remove(curr.finish);
      curr.finish = new fabric.Polyline(showPoints, {
        selectable: false,
        bind: curr.uuid,
        strokeWidth: 12,
        strokeLineJoin: 'round',
        fill: fill,
        stroke,
      });
      this.drawCanvas.add(curr.finish);
      //画箭头三角形
      this.drawCanvas.remove(curr.moveEndArrow);
      let endArrow = this.drawEndArrow(curr.points);
      curr.moveEndArrow = endArrow;
      this.drawCanvas.add(endArrow);

      if(this.draw && this.expand.includes(2)) {
        this.doSave();
      }
    },
    /**
     * 暂存全部后还原颜色
     */
    restoreColor(){
      //暂存还原颜色
      this.drawColor = '#E9EC04';
    },
  },
  beforeDestroy() {
    if(this.resizeObserver) {
      this.resizeObserver.disconnect();
    }
    clearTimeout(this.timing);
  },
}
</script>

<style lang="scss" scoped>
$theme: var(--theme, #FF6A6C);
.draw-area{
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  z-index: 99;
  &.read{
    pointer-events: none;
  }
  $btnScale: var(--btnScale, 1);
  .draw-btns{
    height: 44px;
    line-height: 44px;
    position: absolute;
    left: 50%;
    transform-origin: 50% 100%;
    transform: translateX(-50%) scale($btnScale);
    bottom: 16px;
    background: rgba(51, 51, 51, 0.9);
    color: rgba(255, 255, 255, 0.8);
    padding: 0 15px;
    border-radius: 22px;
    cursor: default;
    transition: all 0.8s;
    display: flex;
    z-index: 9;
    &.hide{
      transform: translate(-50%, 100%) scale($btnScale);
      opacity: 0;
      pointer-events: none;
    }
    .btn{
      margin: 0 8px;
      font-size: 22px;
      cursor: pointer;
      position: relative;
      &:hover{
        color: #fff;
      }
      &.on{
        color: $theme !important;
      }
    }
    .draw-arrow{
      width: 58px;
      padding: 10px 0;
      border: 1px solid $theme;
      border-radius: 3px;
      background: rgba(0, 0, 0, 0.8);
      position: absolute;
      bottom: 100%;
      left: 50%;
      transform: translate(-50%, -10px);
      &:after{
        content: "";
        width: 0;
        height: 0;
        border: 6px solid transparent;
        border-top-color: $theme;
        position: absolute;
        bottom: 0;
        left: 50%;
        transform: translate(-50%, 100%);
      }
      i{
        display: block;
        width: 100%;
        height: 32px;
        line-height: 32px;
        text-align: center;
        font-size: 18px;
        cursor: pointer;
        color: rgba(255, 255, 255, 0.8);
        &:hover{
          background: $theme;
          color: #fff;
        }
        &:last-child{
          transform: rotate(180deg);
        }
      }
    }
  }
  .draw-num{
    display: block;
    width: 28px;
    height: 28px;
    line-height: 26px;
    text-align: center;
    background: #fff;
    border: 1px solid #D4D4D4;
    color: #666;
    font-size: 16px;
    position: absolute;
    cursor: pointer;
  }
  .draw-remove{
    display: block;
    width: 16px;
    height: 16px;
    line-height: 14px;
    text-align: center;
    border: 1px solid #ED211D;
    background: #fff;
    color: #ED211D;
    position: absolute;
    cursor: pointer;
    i{
      font-size: 12px;
      display: block;
      transform: scale(0.6);
    }
  }
  .draw-color{
    display: block;
    width: 32px;
    height: 32px;
    border-radius: 4px;
    box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.15);
    background: #fff;
    text-align: center;
    position: absolute;
    cursor: pointer;
  }
  .draw-layer{
    display: block;
    height: 26px;
    line-height: 26px;
    border-radius: 13px;
    color: #fff;
    padding: 0 8px;
    font-size: 16px;
    position: absolute;
    background: linear-gradient(121deg, #E91D18 0%, #BA261F 100%);
    box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
    white-space: nowrap;

    &:before{
      content: "";
      width: 10px;
      height: 10px;
      border-radius: 50%;
      background: #E41E19;
      position: absolute;
      right: 100%;
      top: 50%;
      transform: translate(4px, -50%);
    }
    &:after{
      content: "";
      width: 4px;
      height: 32px;
      background: #E41E19;
      position: absolute;
      right: 100%;
      top: 50%;
    }
  }
  .on {
    &:before{
      left: 100%;
      transform: translate(-3px, -50%);
    }
    &:after{
      left: 100%;
    }
  }
}
</style>
<style lang="scss">
.c-tooltip2 {
  pointer-events: none;
  z-index: 2050 !important;
}
</style>
